package sale.wxb.loveshopping.config;

import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import sale.wxb.loveshopping.annotation.SwaggerDisplayEnum;
import sale.wxb.loveshopping.enums.BaseEnum;
import springfox.documentation.builders.ModelPropertyBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.service.AllowableListValues;
import springfox.documentation.service.ResolvedMethodParameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.schema.ModelPropertyBuilderPlugin;
import springfox.documentation.spi.schema.contexts.ModelPropertyContext;
import springfox.documentation.spi.service.ParameterBuilderPlugin;
import springfox.documentation.spi.service.contexts.ParameterContext;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * Swagger 枚举列表显示类
 */
@Component
public class SwaggerDisplayEnumConfig implements ModelPropertyBuilderPlugin, ParameterBuilderPlugin {

    @Override
    public void apply(ModelPropertyContext context) {
        if (!context.getBeanPropertyDefinition().isPresent()) {
            return;
        }
        BeanPropertyDefinition beanPropertyDefinition = context.getBeanPropertyDefinition().get();
        SwaggerDisplayEnum swaggerDisplayEnum = beanPropertyDefinition.getField().getAnnotation(SwaggerDisplayEnum.class);
        if (swaggerDisplayEnum == null) {
            return;
        }
        ModelPropertyBuilder builder = context.getBuilder();
        List<String> descList = getEnumDesc(swaggerDisplayEnum);
        builder.description(builder.build().getDescription() + " —— " + String.join(", ", descList));
    }

    @Override
    public void apply(ParameterContext parameterContext) {
        // 找出使用了 SwaggerDisplayEnum 的参数
        List<ResolvedMethodParameter> parameters = parameterContext.getOperationContext().getParameters();
        SwaggerDisplayEnum displayEnum = null;
        String paramName = "";
        for (ResolvedMethodParameter parameter : parameters) {
            SwaggerDisplayEnum annotation = parameter.findAnnotation(SwaggerDisplayEnum.class).orElse(null);

            if (annotation != null) {
                displayEnum = annotation;
                paramName = parameter.defaultName().isPresent() ? parameter.defaultName().get() : "";
                break;
            }
        }

        if (displayEnum == null) {
            return;
        }

        ParameterBuilder parameterBuilder = parameterContext.parameterBuilder();
        // 此处避免同一个接口其中一个使用了SwaggerDisplayEnum注解导致全部参数描述都被更改的问题
        if (!parameterBuilder.build().getName().equals(paramName)) {
            return;
        }
        parameterBuilder.description(displayEnum.name() + " —— " + String.join(", ", getEnumDesc(displayEnum)));
    }

    @Override
    public boolean supports(DocumentationType documentationType) {
        return true;
    }

    /**
     * 生成枚举字符串
     * @param swaggerDisplayEnumField SwaggerDisplayEnum
     * @return ，分割的字符串
     */
    private List<String> getEnumDesc(SwaggerDisplayEnum swaggerDisplayEnumField) {
        // 使用了注解但是不传入枚举类的
        Class<?> value = swaggerDisplayEnumField.value();

        if (value == null) {
            return new ArrayList<>();
        }

        // 得到枚举列表
        BaseEnum[] enumConstants = (BaseEnum[]) value.getEnumConstants();
        List<String> strings = new ArrayList<>();

        for (BaseEnum enumConstant : enumConstants) {
            strings.add(enumConstant.getCode() + "=" + enumConstant.getMessage());
        }

        return strings;
    }
}
